package util.sql;

import java.util.*;
import java.sql.*;

import util.DebugOut;

/**
 * @author Witthold/Korol
 */
/**
 * creates a pool of connections to DB for performance reasons
 */
public class ConnectionManager {

	private String driver = "com.mysql.jdbc.Driver";
	private String databaseUrl = "jdbc:mysql://sqlhost1.informatik.uni-bremen.de/PokerBot";

	private String username = "sergejk8";
	private String password = "b2jL9v2nq2NATBPu";

	private Vector<Connection> connectionPool = new Vector<Connection>();
	private int MAX_POOL_SIZE = 1;


	/**
	 * Constructor default
	 */
	public ConnectionManager() {
		initializeConnectionPool();
	}


	/**
	 * Constructor to nonDefault DB
	 */
	/**
	 * @param driver which dbc driver
	 * @param databaseUrl -
	 * @param username -
	 * @param password -
	 * @param maxPoolSize - how many db-connection should the ConnectionManager allocate
	 */
	public ConnectionManager(String driver, String databaseUrl, String username, String password, int maxPoolSize) {
		this.driver = driver;
		this.databaseUrl = databaseUrl;
		this.username = username;
		this.password = password;
		
		initializeConnectionPool();
	}


	/**
	 * fills connectionPool with connections for numConnections < MAX_POOL_SIZE
	 */
	private void initializeConnectionPool() {
		long a = System.currentTimeMillis();
		DebugOut.showVerboseSqlCM(util.Helper.getTimeMS() + ": ConnectionManager initializeConnectionPool at: ");
		while (!checkIfConnectionPoolIsFull()) {
//			DebugOut.showVerboseSqlCM("Connection Pool is NOT full. Proceeding with adding new connections");
			//Adding new connection instance until the pool is full
			connectionPool.addElement(createNewConnectionForPool());
		}		
		long b = System.currentTimeMillis();
		DebugOut.showVerboseSqlCM(util.Helper.getTimeMS() + ": ConnectionPool has " + connectionPool.size() + " cons. Total time: " + (b - a));
	}


	/**
	 * @return connectionPool.size() < MAX_POOL_SIZE
	 */
	private synchronized boolean checkIfConnectionPoolIsFull() {

		if (connectionPool.size() < MAX_POOL_SIZE) {
			return false;
		}

		return true;
	}


	/**
	 * creates new connection to db
	 * @return new connection
	 */
	private Connection createNewConnectionForPool() {
		Connection connection = null;

		try {
			Class.forName(driver);
			connection = DriverManager.getConnection(databaseUrl, username, password);
//			DebugOut.showVerboseSqlCM("Connection: " + connection);
		} catch (SQLException sqle) {
			System.err.println("SQLException: " + sqle);
			return null;
		} catch (ClassNotFoundException cnfe) {
			System.err.println("ClassNotFoundException: " + cnfe);
			return null;
		}

		return connection;
	}


	/**
	 * @return a connection out of the connectionPool
	 */
	public synchronized Connection getConnectionFromPool() {
		Connection connection = null;

		//Check if there is a connection available. There are times when all the connections in the pool may be used up
		if (connectionPool.size() > 0) {
			connection = (Connection) connectionPool.firstElement();
			connectionPool.removeElementAt(0);
		}
		//Giving away the connection from the connection pool
		return connection;
	}


	/**
	 * Adding the connection from the client back to the connectionPool
	 * 
	 * @param connection -
	 */
	public synchronized void returnConnectionToPool(Connection connection) {
		connectionPool.addElement(connection);
	}
	
	/**
	 *
	 * @return true, if there is at least one connection to the db
	 */
	public boolean connectionSuccess() {
		if(connectionPool.elementAt(0) != null) {
			return true;
		}
		return false;
	}

}
